#ifndef __SQLITE_SQL_EXECUTOR_H_
#define __SQLITE_SQL_EXECUTOR_H_

#include "sqlite-sql-record.h"
#include "sqlite-sql-table-info.h"
#include <deque>
#include "hk_log.h"

#define HK_MACHINE_LOG_SUFFIX_FILE "ir-software-m"

class sql_executor_cmd
{
public:
    sql_executor_cmd();
    virtual ~sql_executor_cmd();

public:
    bool get_db_name( std::string &str_db_path );
    bool open( const std::string &str_path_name, bool b_create );
    bool close();

    bool executor_cmd( const std::string &str_sql_statement, int &i_ret );
    bool executor_cmd( const std::string &str_sql_statement, int &i_ret, int &i_effect_row );

    bool batch_executor( const std::deque<std::string> &str_sql_list )
    {
        return batch_executor_sql_list( str_sql_list );
    }

    bool batch_executor( const std::vector<std::string> &str_sql_list )
    {
        return batch_executor_sql_list( str_sql_list );
    }

    bool batch_executor( const std::list<std::string> &str_sql_list )
    {
        return batch_executor_sql_list( str_sql_list );
    }

    template<typename T>
    bool batch_executor_sql_list( const T& cmd_list )
    {
        if( cmd_list.empty() ){
            return true;
        }

        std::lock_guard<std::mutex> guard(mo_db_lock);
        int i_ret = sqlite3_exec( mp_sql_db, "BEGIN TRANSACTION", NULL, NULL, NULL );

        typename T::const_iterator it = cmd_list.begin();
        for( ; it != cmd_list.end(); ++it ){
            i_ret = sqlite3_exec( mp_sql_db, (*it).c_str(), NULL, NULL, NULL );
            if( SQLITE_OK != i_ret ){
                break;
            }
        }

        if( SQLITE_OK != i_ret ){
            sqlite3_exec( mp_sql_db, "ROLLBACK", NULL, NULL, NULL );
            return false;
        }

        i_ret = sqlite3_exec( mp_sql_db, "COMMIT", NULL, NULL, NULL );
        if( SQLITE_OK != i_ret ){
            HK_LOG_ERROR_EX(HK_MACHINE_LOG_SUFFIX_FILE, "sqlite3_exec COMMIT failed.\n" );
            return false;
        }

        return true;
    }

    bool executor_sql( std::string &str_sql, st_sql_record **p_sr, int &i_ret );
    bool executor_sql( std::string &str_sql, std::vector<std::string> &colum_name_vec, std::list< std::vector<std::string> > &table_info );

    bool close_rs( st_sql_record *p_sr );

    virtual bool get_db_table_context_list( const st_sql_table_info &tbl_info, std::vector<std::string> &col_name_vec, std::list<std::vector<std::string> > &tbl_context );

    //bool get_db_view_info(std::list<st_sql_table_info> &view_list);
    bool get_db_table_info(std::list<st_sql_table_info> &tbl_list);

protected:
    //bool get_view_name_list(std::list<std::string> &view_name_list);
    //bool get_col_info_by_view_name(const std::string &str_view_name, std::list<sql_column_info> &col_list);
    bool get_table_name_list(std::list<std::string> &tbl_name_list);
    bool get_col_info_by_table_name(const std::string &str_table_name, std::list<sql_column_info> &col_list);


private:
    std::mutex  mo_db_lock;
    sqlite3 *mp_sql_db;

    std::string mstr_db_path_name;
};

#endif
